package com.oauth.service.application;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.oauth.service.application.global.beans.GlobalDataType;
import com.oauth.service.application.registry.GlobalRegistryService;
import com.oauth.service.application.registry.beans.ApplicationInfoBean;
import com.oauth.service.application.subscription.ApplicationSubscriptionService;
import com.oauth.service.application.subscription.beans.MemberApplicationRelation;

public class ApplicationServiceImpl implements ApplicationService {

	private GlobalRegistryService<ApplicationInfoBean> mGlobalRegistryService;

	private ApplicationSubscriptionService mApplicationSubscriptionService;

	/**
	 * @param pGlobalRegistryService
	 *            the globalRegistryService to set
	 */
	public void setGlobalRegistryService(
			GlobalRegistryService<ApplicationInfoBean> pGlobalRegistryService) {
		mGlobalRegistryService = pGlobalRegistryService;
	}

	/**
	 * @param pApplicationSubscriptionService
	 *            the applicationSubscriptionService to set
	 */
	public void setApplicationSubscriptionService(
			ApplicationSubscriptionService pApplicationSubscriptionService) {
		mApplicationSubscriptionService = pApplicationSubscriptionService;
	}

	@Override
	public List<ApplicationInfoBean> getSubscribedApplication(Long pMemberId) {
		Set<Long> subscribedApplicationId = getSubscribedApplicationId(pMemberId);
		return mGlobalRegistryService.getApplicationInfo(subscribedApplicationId);
	}

	@Override
	public Set<Long> getSubscribedApplicationId(Long pMemberId) {
		return mApplicationSubscriptionService.getMemberApplications(pMemberId);
	}

	@Override
	public List<ApplicationInfoBean> getUnsubscribedApplication(Long pMemberId) {
		Set<Long> unSubscribedApplicationId = getUnsubscribedApplicationId(pMemberId);
		return mGlobalRegistryService.getApplicationInfo(unSubscribedApplicationId);
	}

	@Override
	public Set<Long> getUnsubscribedApplicationId(Long pMemberId) {
		Set<Long> subscribedApplicationId = getSubscribedApplicationId(pMemberId);
		Set<Long> registerdApplicationId = mGlobalRegistryService.getRegisterdApplicationId();
		registerdApplicationId.removeAll(subscribedApplicationId);
		return registerdApplicationId;
	}

	@Override
	public boolean subscribeApplication(Long pMemberId, Long pApplicationId) {

		MemberApplicationRelation addMemberToApplication = mApplicationSubscriptionService
				.addMemberToApplication(pMemberId, pApplicationId);
		if (addMemberToApplication != null && addMemberToApplication.getApplicationIdSet() != null) {
			if (addMemberToApplication.getApplicationIdSet().contains(pApplicationId)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean unSubscribeApplication(Long pMemberId, Long pApplicationId) {
		Set<Long> memberApplications = mApplicationSubscriptionService
				.getMemberApplications(pMemberId);
		if (memberApplications.contains(pApplicationId)) {
			// Confirmed that member is already subscribed to application.
			MemberApplicationRelation appRelation = mApplicationSubscriptionService
					.removeMemberToApplication(pMemberId, pApplicationId);
			if (!appRelation.getApplicationIdSet().contains(pApplicationId)) {
				// Success
				return true;
			} else {
				return false;
			}
		}

		return true; // Decide what to do here.

	}

	@Override
	public Set<Long> getApplicationIdSetWithDataType(GlobalDataType pGlobalDataType) {
		// NOTE: Provide cache support. Like using temporary hashmap to store
		// application with supported data types.
		Collection<ApplicationInfoBean> registerdApplication = mGlobalRegistryService
				.getRegisterdApplication();
		Set<Long> applicationIdSet = new HashSet<Long>();
		for (ApplicationInfoBean appBean : registerdApplication) {
			if (appBean.getGlobalDataType().contains(pGlobalDataType)) {
				applicationIdSet.add(appBean.getKey());
			}
		}
		return applicationIdSet;
	}

	@Override
	public Set<Long> getApplicationIdSetWithDataTypeForMember(Long pMemberId,
			GlobalDataType pGlobalDataType) {
		Set<Long> subscribedApplication = getSubscribedApplicationId(pMemberId);
		Set<Long> applicationIdSetWithDataType = getApplicationIdSetWithDataType(pGlobalDataType);

		applicationIdSetWithDataType.retainAll(subscribedApplication);
		return applicationIdSetWithDataType;
	}

	@Override
	public Collection<ApplicationInfoBean> getApplicationInfo(Set<Long> pApplicationId) {
		return mGlobalRegistryService.getApplicationInfo(pApplicationId);
	}
}
